#include "monad.hpp"

// ================== 辅助函数 ==================

// 打印结果
template <typename A, typename S, typename W>
void printResult(const std::string& title, const std::tuple<A, S, W>& result)
{
    auto [value, state, log] = result;
    std::cout << "=== " << title << " ===\n";
    std::cout << "Value: ";
    if constexpr (!std::is_same_v<A, Unit>)
    {
        std::cout << value;
    }
    else
    {
        std::cout << "<Unit>";
    }
    std::cout << "\nState: " << state;
    std::cout << "\nLog: \"" << log << "\"\n\n";
}

// ================== 示例用法 ==================

int main()
{
    // 定义环境配置
    struct Environment
    {
        int multiplier;
        std::string baseMessage;
    } env{2, "Hello"};

    // 示例1: 基础操作组合
    auto computation1 = ask<Environment, std::string, int>().flatMap(
        [](const Environment& env)
        {
            return get<Environment, std::string, int>().flatMap(
                [env](int state)
                {
                    int newValue = env.multiplier * state;
                    return tell<Environment, std::string, int>("Calculated: " + std::to_string(newValue))
                        .flatMap([newValue] { return put<Environment, std::string, int>(newValue); })
                        .flatMap([newValue] { return pure<Environment, std::string, int, int>(newValue); });
                });
        });

    auto result1 = computation1.run(env, 3);
    printResult("Computation 1", result1);

    // 示例2: 使用 modify 和链式调用
    auto computation2 = pure<Environment, std::string, int, int>(5).flatMap(
        [](int x)
        {
            return modify<Environment, std::string, int>([x](int s) { return s + x; })
                .flatMap([] { return get<Environment, std::string, int>(); })
                .flatMap(
                    [](int newState)
                    {
                        return tell<Environment, std::string, int>("State is now: " + std::to_string(newState))
                            .flatMap([newState] { return pure<Environment, std::string, int, int>(newState); });
                    });
        });

    auto result2 = computation2.run(env, 10);
    printResult("Computation 2", result2);

    // 示例3: 复杂工作流
    auto workflow = ask<Environment, std::string, int>().flatMap(
        [](const Environment& env)
        {
            return tell<Environment, std::string, int>("Starting with: " + env.baseMessage)
                .flatMap([] { return get<Environment, std::string, int>(); })
                .flatMap(
                    [env](int count)
                    {
                        int newCount = count + 1;
                        return put<Environment, std::string, int>(newCount)
                            .flatMap([] { return tell<Environment, std::string, int>("Incremented counter"); })
                            .flatMap(
                                [env, newCount]
                                {
                                    return pure<Environment, std::string, int, std::string>(env.baseMessage + " count: " + std::to_string(newCount));
                                });
                    });
        });

    auto result3 = workflow.run(env, 0);
    printResult("Workflow", result3);

    return 0;
}